package com.cs.config;

import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

@Configuration
public class RabbitMqConfig implements RabbitTemplate.ReturnsCallback, RabbitTemplate.ConfirmCallback {

    public static final String OPEN_BINDING_QUEUE = "open_binding_queue";
    public static final String EVALUATION_BINDING_QUEUE = "evaluation_binding_queue";
    public static final String CALIBRATE_BINDING_QUEUE = "calibrate_binding_queue";
    public static final String PUBLICY_BINDING_QUEUE = "publicy_binding_queue";
    public static final String BINDING_BINDING_QUEUE = "binding_binding_queue";//投标
    public static final String COMPLETE_BINDING_QUEUE = "complete_binding_queue";//王成


    public static final String OPEN_BINDING_EXCHANGE = "open_binding_exchange";
    public static final String CALIBRATE_BINDING_EXCHANGE = "calibrate_binding_exchange";
    public static final String EVALUATION_BINDING_EXCHANGE = "evaluation_binding_exchange";
    public static final String PUBLICY_BINDING_EXCHANGE = "publicy_binding_exchange";
    public static final String BINDING_BINDING_EXCHANGE = "binding_binding_exchange";
    public static final String COMPLETE_BINDING_EXCHANGE = "complete_binding_exchange";//王成




    public static final String OPEN_BINDING_ROUTE = "open_binding_route";
    public static final String CALIBRATE_BINDING_ROUTE = "calibrate_binding_route";
    public static final String EVALUATION_BINDING_ROUTE = "evaluation_binding_route";
    public static final String PUBLICY_BINDING_ROUTE = "publicy_binding_route";
    public static final String BINDING_BINDING_ROUTE = "binding_binding_route";
    public static final String COMPLETE_BINDING_ROUTE = "complete_binding_route";//王成




    public static final String DEAD_EXCHANGE = "dead_exchange";//死信交换机
    public static final String DEAD_QUEUE = "dead_queue";//死信队列
    public static final String DEAD_ROUTINGKEY = "dead_routingkey";//死信路由

    @Bean
    public Queue deadQueue() {
        return new Queue(DEAD_QUEUE, true, false, false);
    }

    @Bean
    public Exchange deadExchange() {
        return ExchangeBuilder.directExchange(DEAD_EXCHANGE).durable(true).build();
    }

    @Bean
    public Binding deadBind(Queue deadQueue, Exchange deadExchange) {
        return BindingBuilder.bind(deadQueue).to(deadExchange).with(DEAD_ROUTINGKEY).noargs();
    }

    @Bean
    public Queue openBindingQueue() {
        Map<String, Object> map = new HashMap<>();
        map.put("x-dead-letter-exchange", DEAD_EXCHANGE);    //过期的消息给哪个交换机的名字
        map.put("x-dead-letter-routing-key", DEAD_ROUTINGKEY);   //死信交换机把消息个哪个个routingkey
        return new Queue(OPEN_BINDING_QUEUE, true, false, false,map);
    }
    @Bean
    public CustomExchange openBindingExchange() {
        Map<String, Object> args = new HashMap<>();
        args.put("x-delayed-type", "direct");
        return new CustomExchange(OPEN_BINDING_EXCHANGE, "x-delayed-message", true, false, args);
    }
    @Bean
    public Binding openBinding() {
        return BindingBuilder.bind(openBindingQueue()).to(openBindingExchange()).with(OPEN_BINDING_ROUTE).noargs();
    }

    @Override
    public void returnedMessage(ReturnedMessage returnedMessage) {
        System.out.println("returnedMessage = " + returnedMessage);
        //添加到死信
    }

    @Override
    public void confirm(CorrelationData correlationData, boolean b, String s) {
        if (b) {
            System.out.println("correlationData = " + correlationData);
        } else {
            System.out.println(" failed "+correlationData.getReturned());
        }
    }


    @Bean
    public RabbitTemplate rabbitTemplate(CachingConnectionFactory connectionFactory) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        //设置给rabbitTemplate
        rabbitTemplate.setConfirmCallback(this);
        rabbitTemplate.setReturnsCallback(this);
        //默认中交换机处理失败了是不处理的，也不会执行回调函数。设置为true后交换机处理失败了则会将消息回退到生产者
        rabbitTemplate.setMandatory(false);

        return rabbitTemplate;
    }

    //序列化jackson
    @Bean
    public MessageConverter jackson2JsonMessageConverter() {
        return new Jackson2JsonMessageConverter();
    }

    @Bean
    public Queue evaluationQueue() {
        return new Queue(EVALUATION_BINDING_QUEUE, true, false, false);
    }
    @Bean
    public CustomExchange evaluationExchange() {
        Map<String, Object> args = new HashMap<>();
        args.put("x-delayed-type", "direct");
        return new CustomExchange(EVALUATION_BINDING_EXCHANGE, "x-delayed-message", true, false, args);
    }
    @Bean
    public Binding evaluationBinding() {
        return BindingBuilder.bind(evaluationQueue()).to(evaluationExchange()).with(EVALUATION_BINDING_ROUTE).noargs();
    }

    @Bean
    public Queue calibrateQueue(){
        //没有配置额外的死信交换机,数据丢失就没了
        return new Queue(CALIBRATE_BINDING_QUEUE, true, false, false);
    }
    @Bean
    public CustomExchange calibrateExchange(){
        Map<String, Object> args = new HashMap<>();
        args.put("x-delayed-type", "direct");
        return new CustomExchange(CALIBRATE_BINDING_EXCHANGE, "x-delayed-message", true, false, args);
    }
    @Bean
    public Binding  calibrateBinding(){
        return BindingBuilder.bind(calibrateQueue()).to(calibrateExchange()).with(CALIBRATE_BINDING_ROUTE).noargs();
    }
    @Bean
    public Queue publicyQueue(){
        return new Queue(PUBLICY_BINDING_QUEUE, true, false, false);
    }
    @Bean
    public CustomExchange publicyExchange(){
        Map<String, Object> args = new HashMap<>();
        args.put("x-delayed-type", "direct");
        return new CustomExchange(PUBLICY_BINDING_EXCHANGE, "x-delayed-message", true, false, args);
    }

    @Bean
    public Binding  publicyBinding(){
        return BindingBuilder.bind(publicyQueue()).to(publicyExchange()).with(PUBLICY_BINDING_ROUTE).noargs();
    }

    @Bean
    public Queue bindingQueue(){
        return new Queue(BINDING_BINDING_QUEUE, true, false, false);
    }
    @Bean
    public CustomExchange bindingExchange(){
        Map<String, Object> args = new HashMap<>();
        args.put("x-delayed-type", "direct");
        return new CustomExchange(BINDING_BINDING_EXCHANGE, "x-delayed-message", true, false, args);
    }

    @Bean
    public Binding bindingBinding(){
        return BindingBuilder.bind(bindingQueue()).to(bindingExchange()).with(BINDING_BINDING_ROUTE).noargs();
    }

    @Bean
    public Queue completeQueue(){
        return new Queue(COMPLETE_BINDING_QUEUE, true, false, false);
    }
    @Bean
    public CustomExchange completeExchange(){
        Map<String, Object> args = new HashMap<>();
        args.put("x-delayed-type", "direct");
        return new CustomExchange(COMPLETE_BINDING_EXCHANGE, "x-delayed-message", true, false, args);
    }

    @Bean
    public Binding completeBinding(){
        return BindingBuilder.bind(completeQueue()).to(completeExchange()).with(COMPLETE_BINDING_ROUTE).noargs();
    }
}
